// http.ts
import axios, { AxiosRequestConfig, AxiosResponse } from 'axios'
import qs from "qs"
import Cookie from "js-cookie"

// 声明一个 Map 用于存储每个请求的标识 和 取消函数
const pending = new Map()
/**
 * 添加请求
 * @param {Object} config
 */
const addPending = (config: AxiosRequestConfig) => {
	const url = [
		config.method,
		config.url,
		qs.stringify(config.params),
		qs.stringify(config.data)
	].join('&')
	config.cancelToken = config.cancelToken || new axios.CancelToken(cancel => {
		if (!pending.has(url)) { // 如果 pending 中不存在当前请求，则添加进去
			pending.set(url, cancel)
		}
	})
}
/**
 * 移除请求
 * @param {Object} config
 */
const removePending = (config: AxiosRequestConfig) => {
	const url = [
		config.method,
		config.url,
		qs.stringify(config.params),
		qs.stringify(config.data)
	].join('&')
	if (pending.has(url)) { // 如果在 pending 中存在当前请求标识，需要取消当前请求，并且移除
		const cancel = pending.get(url)
		cancel(url)
		pending.delete(url)
	}
}

/**
 * 清空 pending 中的请求（在路由跳转时调用）
 */
export const clearPending = () => {
	for (const [url, cancel] of pending) {
		cancel(url)
	}
	pending.clear()
}

/**
 * 创建service
 */
const service = axios.create({
	baseURL: '/api',
	withCredentials: true, // send cookies when cross-domain requests
	timeout: 5000 // request timeout
})

// 请求拦截器
service.interceptors.request.use((config: AxiosRequestConfig) => {
	removePending(config) // 在请求开始前，对之前的请求做检查取消操作
	addPending(config) // 将当前请求添加到 pending 中
	// let token = localStorage.getItem('token')
	let token = Cookie.get('token')
	if (token) {
		if (config?.headers) {
			// @ts-ignore
			config.headers['Authorization'] = `${token}`;
		}
	}
	return config
}, (error: { data: { msg?: any } }) => {
	// 错误抛到业务代码
	error.data = {}
	error.data.msg = '服务器异常，请联系管理员！'
	return Promise.resolve(error)
})

// 响应拦截器
service.interceptors.response.use((response: AxiosResponse) => {
	removePending(response) // 在请求结束后，移除本次请求
	const code = response.data.code
	let msg = ''
	if (code !== 200) {
		if (typeof response.data === 'string') {
			response.data = { msg }
		} else {
			response.data.msg = msg
		}
		alert(response.data.msg)
		return Promise.reject('接口错误')
	}
	return response;
})

export default service



